package com.xiongmao.webflux.gateway;

import com.xiongmao.webflux.auth.service.AuthService;
import com.xiongmao.webflux.common.CommonConst;
import com.xiongmao.webflux.common.ResponseCollect;
import com.xiongmao.webflux.utils.RedisUtils;
import com.xiongmao.webflux.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.stream.Stream;

/**
 * @Author: lao_hu
 * @Date: 2022/2/25 15:25
 * @Description: webfulx 的过滤器
 */
@Component
public class GlobalFilter implements WebFilter {
    @Autowired
    private AuthService authService;
    @Autowired
    private RedisUtils redisUtils;

    private static final Logger logger = LoggerFactory.getLogger(GlobalFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String address = exchange.getRequest().getRemoteAddress().getAddress().toString();
        HttpHeaders headers = exchange.getRequest().getHeaders();
        //记录响应header头语言信息与请求的一致
        String language = headers.getFirst("Accept-Language") == null ? "zh": headers.getFirst("Accept-Language");
        exchange.getResponse().getHeaders().add("Accept-Language",language);
        String cookies = headers.get("Cookie") == null ? "" : headers.get("Cookie").toString();
        String[]  cookieList = cookies.replace("[","").replace("]","").split(";");
        String sid = "";
        if(null != cookies && cookieList.length >0){
            for (int i = 0; i < cookieList.length; i++) {
                if("sid".equals(cookieList[i].split("=")[0].trim())){
                    sid = cookieList[i].split("=")[1].trim();
                    break;
                }
            }
        }
        String url = exchange.getRequest().getPath().toString();
        //登录
        if(Stream.of(CommonConst.LOGIN_PATH.split(",")).anyMatch(ignoreUrl -> url.startsWith(ignoreUrl == null ? null : ignoreUrl.trim()))){
            redisUtils.delete(CommonConst.SESSION_CACHE + (StringUtil.isBlank(sid) ? "":sid));
            return chain.filter(exchange);
        }
        //登出
        if(CommonConst.LOGOUT_PATH.equals(url)){
            redisUtils.delete(CommonConst.SESSION_CACHE + (StringUtil.isBlank(sid) ? "":sid));
            return ResponseCollect.successMono(exchange);
        }
        //放行不需要登录的请求
        if(Stream.of(CommonConst.ignoreUrls.split(",")).anyMatch(ignoreUrl -> url.startsWith(ignoreUrl == null ? null : ignoreUrl.trim()))){
            return chain.filter(exchange);
        }
        //不属于上述请求，且sid为空时，提示无权限异常
        if(StringUtils.isBlank(sid)){
            //页面访问时，无权限可在此处理，携带请求地址转到登录页
            if(url.endsWith(".html")){
                return Mono.fromRunnable(()->{
                    exchange.getResponse().setStatusCode(HttpStatus.FOUND);
                    exchange.getResponse().getHeaders().setLocation(URI.create("https://www.baidu.com/"));
                });
            }
            return ResponseCollect.unauthorized(exchange);
        }
        //sid存在则刷新，不存在则提示登录失效
        if(!authService.isExitAndFrash(sid)){
            return ResponseCollect.unauthorized(exchange);
        }
        //todo 权限校检目前写死的校检成功
        if (authService.permission(sid, url)) {
            ServerHttpRequest.Builder builder = request.mutate();
            //往其他应用分发请求时，可以在此处处理header信息
            builder.header("sid", sid);
            builder.header("X-Real-IP",address);
            return chain.filter(exchange.mutate().request(builder.build()).build());
        }else {
            //网关拒绝，返回401
            return ResponseCollect.unauthorized(exchange);
        }
    }
}
